#include "./WizVFSBlockStorageParam.hpp"
#include "./WizVFSBlockStorageBlock.hpp"

namespace Wiz
{
    namespace VFS
    {
        namespace BlockStorage
        {
            namespace Block
            {
                ::Wiz::Void::Type Type::WriteInfoAndAdvance(::Wiz::VFS::BlockStorage::Param::InOut IOParam)
                {
                    IOParam.m_AccessorPtr->MoveTo(m_Position);
                    ::Wiz::VFS::BlockStorage::BlockInfo::Type BlockInfo;

                    BlockInfo.m_CheckCode = m_CheckCode;
                    BlockInfo.m_PreChunkID = m_PreChunkID;
                    BlockInfo.m_PreBlockID = m_PreBlockID;
                    BlockInfo.WriteAndAdvance(IOParam.m_AccessorPtr);
                }

                ::Wiz::UInt32::Type Type::ReadNextAvailableBlock(::Wiz::VFS::BlockStorage::Param::InOut IOParam)
                {
                    IOParam.m_AccessorPtr->MoveTo(m_Position);
                    ::Wiz::UInt32::Type NextAvailable;
                    IOParam.m_AccessorPtr->Read(NextAvailable);
                    return NextAvailable;
                }

                ::Wiz::Void::Type Type::ReadInfoAndAdvance(::Wiz::VFS::BlockStorage::Param::InOut IOParam)
                {
                    IOParam.m_AccessorPtr->MoveTo(m_Position);
                    ::Wiz::VFS::BlockStorage::BlockInfo::Type BlockInfo;
                    BlockInfo.ReadAndAdvance(IOParam.m_AccessorPtr);

                    IOParam.m_BlockInfo.m_CheckCode = BlockInfo.m_CheckCode;
                    IOParam.m_BlockInfo.m_PreChunkID = BlockInfo.m_PreChunkID;
                    IOParam.m_BlockInfo.m_PreBlockID = BlockInfo.m_PreBlockID;
                }

                //////////////////////////////////////////////////////////////////////////

                ::Wiz::UInt32::Type Type::Write(::Wiz::VFS::BlockStorage::Param::InOut IOParam)
                {
                    ::Wiz::UInt32::Type NextAvailable = this->ReadNextAvailableBlock(IOParam);

                    m_CheckCode = IOParam.m_BlockInfo.m_CheckCode;
                    m_PreChunkID = IOParam.m_BlockInfo.m_PreChunkID;
                    m_PreBlockID = IOParam.m_BlockInfo.m_PreBlockID;

                    IOParam.m_AccessorPtr->Move(sizeof(::Wiz::VFS::BlockStorage::BlockInfo::Type));

                    ::Wiz::Byte::Ptr    CurrPtr     = IOParam.m_DataPtr + IOParam.m_DataCurrPos;
                    ::Wiz::Size::Type   WriteCount  = ::Wiz::Min2(IOParam.m_DataSize - IOParam.m_DataCurrPos, IOParam.m_BlockSize);
                    
                    IOParam.m_AccessorPtr->Write(CurrPtr, WriteCount);
                    IOParam.m_DataCurrPos += WriteCount;

                    IOParam.m_WriteBackBlockArray.PushBack(*this);

                    return NextAvailable;
                }

                ::Wiz::Void::Type Type::Read(::Wiz::VFS::BlockStorage::Param::InOut IOParam)
                {
                    this->ReadInfoAndAdvance(IOParam);
                    ::Wiz::Byte::Ptr    CurrPtr     = IOParam.m_DataPtr + IOParam.m_DataCurrPos;
                    ::Wiz::Size::Type   ReadCount  = ::Wiz::Min2(IOParam.m_DataSize - IOParam.m_DataCurrPos, IOParam.m_BlockSize);

                    IOParam.m_AccessorPtr->Read(CurrPtr, ReadCount);
                    IOParam.m_DataCurrPos -= IOParam.m_BlockSize;
                }
            } /// end of namespace Block
        } /// end of namespace BlockStorage
    } /// end of namespace Accessor
} /// end of namespace Wiz

